#include <func.h>
#include "ThreadPool.h"
#include "Network.h"

#define MAXLINE 1024

int exitpipes[2];
void exit_handler(int signo) {
    write(exitpipes[1], "1", 1);
}

int main(int argc, char *argv[])
{
    pipe(exitpipes);
    pid_t pid = fork();
    if (pid != 0) {
        // 父进程
        close(exitpipes[0]);
        // 捕获 SIGURS1 信号
        if (signal(SIGUSR1, exit_handler) == SIG_ERR) {
            error(1, errno, "signal");
        }
        // 等待子进程结束
        wait(NULL);
        exit(0);
    }
    // 子进程
    close(exitpipes[1]);

    // 创建进程池
    // 父进程应该保留子进程的数据
    int num_threads = 8;
    ThreadPool* pool = create_thread_pool(num_threads);


    int epfd = epoll_create(1);
    epoll_add(epfd, exitpipes[0]);

    // 监听端口
    int listenfd = tcp_listen();
    printf("INFO: waiting for connection...\n");
    epoll_add(epfd, listenfd);

    int max_events = 1024;
    struct epoll_event* ready_events = 
        (struct epoll_event*) calloc(max_events, sizeof(struct epoll_event));

    // Main loop
    for(;;) {
        int n = epoll_wait(epfd, ready_events, max_events, -1);

        for (int i = 0; i < n; i++) {
            if (ready_events[i].data.fd == listenfd) {
                // 有新的连接
                struct sockaddr_storage client_addr;
                socklen_t addrlen = sizeof(client_addr);

                int connfd = accept(listenfd, 
                                    (struct sockaddr*)&client_addr,
                                    &addrlen);
                // 打印客户端地址
                char ip_str[50];
                inet_ntop(client_addr.ss_family, 
                          get_ip_addr((struct sockaddr*)&client_addr), 
                          ip_str, 50);

                printf("INFO: new connection from %s, on socket %d\n", ip_str, connfd);
                epoll_add(epfd, connfd);

            } else if (ready_events[i].data.fd == exitpipes[0]) {
                printf("INFO: received exit signal\n");
                // 通知各个子线程退出
                for(int j = 0; j < pool->num_threads; j++) {
                    // pthread_cancel(pool->threads[j]);
                    blockq_push(pool->task_queue, -1);
                }
                // 等待各个子线程退出
                for(int j = 0; j < pool->num_threads; j++) {
                    pthread_join(pool->threads[j], NULL);
                }
                printf("INFO: main thread exits\n");
                pthread_exit(0);

            } else {
                // 客户端有请求
                int connfd = ready_events[i].data.fd;
                // 接收数据，解析请求
                char cmd[MAXLINE];
                int n = recv(connfd, cmd, MAXLINE, 0);

                if (n == 0) {
                    printf("INFO: client shutdown\n");
                    close(connfd);
                } else if (n < 0) {
                    error(0, errno, "recv");
                    close(connfd);
                } else {
                    // 解析任务，把任务添加到任务队列
                    blockq_push(pool->task_queue, connfd);
                }
            }
        }
    }

    return 0;
}

